﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Qianke.Core.Common
{
    public static class ListHelper
    {

        public static async Task<List<TDes>> SelectAsync<TSrc,TDes>(this IEnumerable<TSrc> dataList,Func<TSrc,int,Task<TDes>> fnGetNewObject)
        {
            var result = new List<TDes>();
            var nIndex = 0;
            foreach (var data in dataList)
                result.Add(await fnGetNewObject(data,nIndex++));
            return result;
        }

        public static Task<List<TDesc>> SelectAsync<TSrc,TDesc>(this IEnumerable<TSrc> dataList,Func<TSrc,Task<TDesc>> fnSelect)
        {
            return dataList.SelectAsync((u, n) => fnSelect(u));
        }

        public static async Task ForEachAsync<TSrc>(this IEnumerable<TSrc> dataList,Func<TSrc,int,Task> fnForEach)
        {
            var nIndex = 0;
            foreach (var data in dataList)
                await fnForEach(data,nIndex++);
        }


        public static Task ForEachAsync<TSrc>(this IEnumerable<TSrc> dataList,Func<TSrc,Task> fnForEach)
        {
            return dataList.ForEachAsync((u, n) => fnForEach(u));
        }


        public static async Task<List<TSrc>> WhereAsync<TSrc>(this IEnumerable<TSrc> dataList,Func<TSrc,int,Task<bool>> fnWhere)
        {
            List<TSrc> nList = new List<TSrc>();
            var nIndex = 0;
            foreach(var data in dataList)
            {
                if (await fnWhere(data,nIndex))
                    nList.Add(data);
                nIndex++;
            }
            return nList;
        }

        public static Task<List<TSrc>> WhereAsync<TSrc>(this IEnumerable<TSrc> dataList,Func<TSrc,Task<bool>> fnWhere)
        {
            return dataList.WhereAsync((u,n) => fnWhere(u));
        }


        public static async Task<bool> ExistsAsync<TSrc>(this IEnumerable<TSrc> dataList,Func<TSrc,int,Task<bool>> fnExists)
        {
            var nIndex = 0;
            foreach(var data in dataList)
            {
                if (await fnExists(data, nIndex++))
                    return true;
            }
            return false;
        }

        public static Task<bool> ExistsAsync<TSrc>(this IEnumerable<TSrc> dataList,Func<TSrc,Task<bool>> fnExists)
        {
            return dataList.ExistsAsync((u, n) => fnExists(u));
        }


        public static IEnumerable<TKey> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> comparer) where TKey : struct, IComparable
        {
            List<TKey> nList = new List<TKey>();
            foreach (var sre in source)
            {
                TKey tVal = comparer(sre);
                if (!nList.Exists(u => u.Equals(tVal)))
                    nList.Add(comparer(sre));
            }
            return nList;
        }

        public static IEnumerable<string> Distinct<TSource>(this IEnumerable<TSource> source, Func<TSource, string> comparer)
        {
            List<string> nList = new List<string>();
            foreach (var sre in source)
            {
                string tVal = comparer(sre);
                if (!nList.Exists(u => u.Equals(tVal)))
                    nList.Add(comparer(sre));
            }
            return nList;
        }
    }
}
